#include <iostream>
#include <functional>

using std::cout;
using std::endl;
using std::bind;
using std::function;

int add(int x, int y)
{
    cout << "int add(int, int)" << endl;
    return x + y;
}

class Example
{
public:
    Example(){

    }

    Example(const Example &rhs){
        cout<<"拷贝"<<endl;
    }

    int add(int x, int y)
    {
        cout << "int Example::add(int, int)" << endl;
        return x + y;
    }

    int data = 10000;
};

void test()
{
    //int(int, int)--->int()
    //int() f = bind(add, 1, 3);   报错
    
    //int f = bind(add, 1, 3);
    //bind返回的结果是一个可调用对象（callable object）。
    //使用 int f 来接收 bind 的返回值，这是不正确的，因为bind返回的类型不是 int。
    
    function<int()> f = bind(add, 1, 3);
    //function可以存函数类型，可以将其称为函数的容器
    
    /*
        template<class R, class... Args>
        class function<R(Args...)>
    */
    cout << "f() = " << f() << endl;

    cout << endl;
    Example ex;
    //int(Example *, int, int)--->int()
    function<int()> f2 = bind(&Example::add, ex, 30, 70);
    //这里传入ex，会拷贝一次
    cout <<"f2() = " << f2() << endl;

    cout << endl;
    function<int()> f3 = bind(&Example::add, &ex, 30, 70);
    //多线程情况下，如果ex已经被释放了，那么这里传入的就变空指针
    cout <<"f3() = " << f3() << endl;

    cout << endl;
    //占位符
    //int(int, int)---->int(int)
    function<int(int)> f4 = bind(add, 1, std::placeholders::_1);
    cout << "f4(9) = " << f4(9) << endl;
    
    //如果是两个占位符：
    //function<int(int,int)> f4 = bind(add, std::placeholders::_1, std::placeholders::_2);
    //cout << "f4(9,9) = " << f4(9,9) << endl;

    cout << endl;
    Example ex2;
    //bind还可以绑定数据成员
    function<int()> f5 = bind(&Example::data, &ex2);
    cout << "f5() = " << f5() << endl;
    
    cout << endl;
    function<int(int,int)> f6 = [](int a, int b){
        return a+b;
    };
    cout<<f6(1,2)<<endl;
}

int main()
{
    test();
    return 0;
}


